cordova.define("mamp-plugin-file", function(require, exports, module) {

var argscheck = require('cordova/argscheck'),
    exec = require('cordova/exec'),
    cordovaFile = require('cordova-plugin-file.fileSystemPaths'),
    cordovaRequestLocalFileSystem = require('cordova-plugin-file.resolveLocalFileSystemURI'),
    DirectoryReader = require('cordova-plugin-file.DirectoryReader');
    FileReader = require('cordova-plugin-file.FileReader');
    FileTransfer = require('cordova-plugin-file-transfer.FileTransfer');
    FileSystem = require('cordova-plugin-file.FileSystem');

var mampFile = {

	FileStoragePath:{
      DocumentPath : 0,
      TemporaryPATH : 1,
      SharedPath : 2
  	},

  	FileReadType:{
      Text : 0,
      DataURL : 1,
      BinaryString : 2,
      ArrayBuffer: 3
  	},
    
    _generateError:function(code, msg) {
    	var error = {"code":code, "msg":msg};
    	return error;
    },

    _parseFilePath:function(path) {
    	var resolvedPath = null;
    	if (path === mampFile.FileStoragePath.DocumentPath) {
    		if (cordova.platformId === 'ios'){
    			resolvedPath = cordovaFile.file.documentsDirectory;
    		} else if (cordova.platformId === 'android') {
                resolvedPath = cordovaFile.file.externalApplicationStorageDirectory;
    		} else {

    		}
    	} else if (path === mampFile.FileStoragePath.TemporaryPATH) {
    		if (cordova.platformId === 'ios'){
    			resolvedPath = cordovaFile.file.tempDirectory;
    		} else if (cordova.platformId === 'android') {
                resolvedPath = cordovaFile.file.externalCacheDirectry;
    		} else {

    		}
    	} else if (path === mampFile.FileStoragePath.SharedPath) {
    		if (cordova.platformId === 'ios'){
    			resolvedPath = cordovaFile.file.dataDirectory;
    		} else if (cordova.platformId === 'android') {
                resolvedPath = cordovaFile.file.externalDataDirectory;
    		} else {

    		}
    	} else {

    	}
    	return resolvedPath;
    },

    _createFile:function(dirEntry, fileName, isAppend, successCallback, errorCallback) {
	    // Creates a new file or returns the file if it already exists.
	    dirEntry.getFile(fileName, {create: true, exclusive: true}, function(fileEntry) {

	        mampFile._writeFile(fileEntry, null, isAppend, successCallback, errorCallback);

	    }, errorCallback);

	},

	_writeFile:function(fileEntry, dataObj, isAppend, successCallback, errorCallback) {
	    // Create a FileWriter object for our FileEntry (log.txt).
	    fileEntry.createWriter(function (fileWriter) {

	        fileWriter.onwriteend = function(ret) {
	            console.log("Successful file read...");
	            if (successCallback) {
	            	successCallback(ret);
	            }
	        };

	        fileWriter.onerror = function (e) {
	            console.log("Failed file read: " + e.toString());
	            if (errorCallback) {
	            	errorCallback(e);
	            }
	        };

	        // If we are appending data to file, go to the end of the file.
	        if (isAppend) {
	            try {
	                fileWriter.seek(fileWriter.length);
	            }
	            catch (e) {
	                console.log("file doesn't exist!");
	                errorCallback(e);
	            }
	        }
	        fileWriter.write(dataObj);
	    });
	},

	/*  -----  BEGIN - Object Definition  -----  */
	 // 以下为不同回调类型中的参数结构定义.

	 /* DirectoryEntry {
	 *  	name,            目录名称，类型为string
	 *  	fullPath         完整路径，类型为string
	 *  }
	 */

	/* FileEntry {
	 *  	name,            文件名称，类型为string
	 *      fullPath         完整路径，类型为string
	 *  }
	 */

	 /* Entry {
	 *  	isDirectory,     该对象是否为目录，类型为bool
	 *	    isFile，         该对象是否为文件，类型为bool
	 *	    name,            目录名称，类型为string
	 *  	fullPath         完整路径，类型为string
	 *  }
	 */

	 /* Metadata {
	 *  	size,                    文件或目录大小
	 *      modificationTime         文件或目录的最后修改时间
	 *  }
	 */

	 /*  -----  END - Object Definition  -----  */

	/**
	 * 在指定目录创建新目录.
	 *
	 * @param FileStoragePath path            根目录类型
	 * @param String dirName                  目录相对路径，如"test/data/data2"将在指定根目录创建形如 test/data/data2 的目录结构
	 * @param {function} successCallback      (OPTIONAL)创建目录成功的回调， 回调参数为DirectoryEntry类型对象. 
	 * @param {function} errorCallback        (OPTIONAL)创建目录失败的回调
	 */
	createDir:function(path, dirName, successCallback, errorCallback) {
		var resolvedPath = mampFile._parseFilePath(path);
		if (resolvedPath !== null) {
			cordovaRequestLocalFileSystem.resolveLocalFileSystemURL(resolvedPath, function (dirEntry) {
    			dirEntry.getDirectory(dirName, { create: true, exclusive: true }, successCallback, errorCallback);
    		}, errorCallback);
		} else {
			console.log("INVALID Path!!");
			errorCallback(mampFile._generateError(1, "INVALID Path!!"));
		}
	},

	/**
	 * 删除指定的目录.
	 *
	 * @param FileStoragePath path            根目录类型
	 * @param String dirName                  目录相对路径，如"test/data/data2"
	 * @param {function} successCallback      (OPTIONAL)删除目录成功的回调 
	 * @param {function} errorCallback        (OPTIONAL)删除目录失败的回调
	 */
	removeDir:function(path, dirName, successCallback, errorCallback) {
		var resolvedPath = mampFile._parseFilePath(path);
		if (resolvedPath !== null) {
			cordovaRequestLocalFileSystem.resolveLocalFileSystemURL(resolvedPath, function (dirEntry) {
    			dirEntry.getDirectory(dirName, { create: false, exclusive: false }, function(directEntry) {
    				directEntry.removeRecursively(successCallback, errorCallback)}, errorCallback);
    		}, errorCallback);
		} else {
			console.log("INVALID Path!!");
			errorCallback(mampFile._generateError(1, "INVALID Path!!"));
		}
	},

	/**
	 * 获取指定的目录的内容列表.
	 *
	 * @param FileStoragePath path            根目录类型
	 * @param String dirName                  目录相对路径，如"test/data/data2"
	 * @param {function} successCallback      (OPTIONAL)获取目录内容列表成功的回调，参数为数组类型，成员均为 Entry 类型对象
	 * @param {function} errorCallback        (OPTIONAL)获取目录内容失败的回调
	 */
	readEntries:function(path, dirName, successCallback, errorCallback) {
		var resolvedPath = mampFile._parseFilePath(path);
		if (resolvedPath !== null) {
			cordovaRequestLocalFileSystem.resolveLocalFileSystemURL(resolvedPath, function (dirEntry) {
    			dirEntry.getDirectory(dirName, { create: false, exclusive: false }, function(directEntry) {
    				var dReader = new DirectoryReader(directEntry.toURL());
    				if (dReader) {
    					dReader.readEntries(successCallback, errorCallback);
    				} else {
    					if (errorCallback) {
    						errorCallback(mampFile._generateError(1, "FAILED to create DirectoryReader!!"));
    					}
    				}
    			}, errorCallback);
    		}, errorCallback)
		} else {
			console.log("INVALID Path!!");
			errorCallback(mampFile._generateError(1, "INVALID Path!!"));
		}
	},

	/**
	 * 在指定的目录创建文件.
	 *
	 * @param FileStoragePath path            根目录类型
	 * @param String fileName                 文件相对路径，如"test/data/data2.txt"
	 * @param {function} successCallback      (OPTIONAL)创建文件成功的回调，参数为FileEntry类型对象
	 * @param {function} errorCallback        (OPTIONAL)创建文件失败的回调
	 */
	createFile:function(path, fileName, successCallback, errorCallback) {
		var resolvedPath = mampFile._parseFilePath(path);
		if (resolvedPath !== null) {
			cordovaRequestLocalFileSystem.resolveLocalFileSystemURL(resolvedPath, function (dirEntry) {
    			mampFile._createFile(dirEntry, fileName, null, successCallback, errorCallback);
    		}, errorCallback);
		} else {
			console.log("INVALID Path!!");
			errorCallback(mampFile._generateError(1, "INVALID Path!!"));
		}
	},

	/**
	 * 删除指定文件.
	 *
	 * @param FileStoragePath path            根目录类型
	 * @param String fileName                 文件相对路径，如"test/data/data2.txt"
	 * @param {function} successCallback      (OPTIONAL)删除文件成功的回调
	 * @param {function} errorCallback        (OPTIONAL)删除文件失败的回调
	 */
	removeFile:function(path, fileName, successCallback, errorCallback) {
		var resolvedPath = mampFile._parseFilePath(path);
		if (resolvedPath !== null) {
			cordovaRequestLocalFileSystem.resolveLocalFileSystemURL(resolvedPath, function (dirEntry) {
    			dirEntry.getFile(fileName, {create: false, exclusive: false}, function(fileEntry) {
	        		fileEntry.remove(successCallback, errorCallback);
	    		}, errorCallback);
    		}, errorCallback);
		} else {
			console.log("INVALID Path!!");
			errorCallback(mampFile._generateError(1, "INVALID Path!!"));

		}
	},

	/**
	 * 复制文件或目录到指定位置.
	 *
	 * @param FileStoragePath fromPath         源根目录类型
	 * @param String fromRelativePath          源文件或目录的相对路径，如"test/data/data2.txt"
	 * @param FileStoragePath toPath           复制到的路径的根目录类型
	 * @param String toRelativePath            复制到的相对路径，如"test2/data/data2.txt"
	 * @param {function} successCallback       (OPTIONAL)复制成功的回调
	 * @param {function} errorCallback         (OPTIONAL)复制失败的回调
	 */
	copyTo:function(fromPath, fromRelativePath, toPath, toRelativePath, successCallback, errorCallback) {
		var resolvedFromPath = mampFile._parseFilePath(fromPath);
		if (resolvedFromPath !== null) {
			var resolvedToPath = mampFile._parseFilePath(toPath);

			if (resolvedToPath !== null) {
				cordovaRequestLocalFileSystem.resolveLocalFileSystemURL(resolvedFromPath, function (dirEntry) {

    				dirEntry.getFile(fromRelativePath, {create: false, exclusive: false}, function(fileEntry) {
    					cordovaRequestLocalFileSystem.resolveLocalFileSystemURL(resolvedToPath, function(toDirEntry) {
							fileEntry.copyTo(toDirEntry, toRelativePath, successCallback, errorCallback);
    					}, errorCallback);
	        			
	    			}, errorCallback);
    			}, errorCallback);
			} else {
				console.log("INVALID To Path!!");
				errorCallback(mampFile._generateError(1, "INVALID Path!!"));
			}

			
		} else {
			console.log("INVALID From Path!!");
			errorCallback(mampFile._generateError(1, "INVALID Path!!"));
		}
	},

	/**
	 * 移动文件或目录到指定位置.
	 *
	 * @param FileStoragePath fromPath         源根目录类型
	 * @param String fromRelativePath          源文件或目录的相对路径，如"test/data/data2.txt"
	 * @param FileStoragePath toPath           移动到的路径的根目录类型
	 * @param String toRelativePath            移动到的相对路径，如"test2/data/data2.txt"
	 * @param {function} successCallback       (OPTIONAL)移动成功的回调
	 * @param {function} errorCallback         (OPTIONAL)移动失败的回调
	 */
	moveTo:function(fromPath, fromRelativePath, toPath, toRelativePath, successCallback, errorCallback) {
		var resolvedFromPath = mampFile._parseFilePath(fromPath);
		if (resolvedFromPath !== null) {
			var resolvedToPath = mampFile._parseFilePath(toPath);

			if (resolvedToPath !== null) {
				cordovaRequestLocalFileSystem.resolveLocalFileSystemURL(resolvedFromPath, function (dirEntry) {

    				dirEntry.getFile(fromRelativePath, {create: false, exclusive: false}, function(fileEntry) {
    					cordovaRequestLocalFileSystem.resolveLocalFileSystemURL(resolvedToPath, function(toDirEntry) {
							fileEntry.moveTo(toDirEntry, toRelativePath, successCallback, errorCallback);
    					}, errorCallback);
	        			
	    			}, errorCallback);
    			}, errorCallback);
			} else {
				console.log("INVALID To Path!!");
				errorCallback(mampFile._generateError(1, "INVALID Path!!"));
			}

			
		} else {
			console.log("INVALID From Path!!");
			errorCallback(mampFile._generateError(1, "INVALID Path!!"));
		}
	},

	/**
	 * 获取文件或目录的属性.
	 *
	 * @param FileStoragePath path             根目录类型
	 * @param String fromRelativePath          文件或目录的相对路径，如"test/data/data2.txt"
	 * @param {function} successCallback       (OPTIONAL)获取成功的回调，参数类型为Metadata
	 * @param {function} errorCallback         (OPTIONAL)获取失败的回调
	 */
	getMetadata:function(path, fileName, successCallback, errorCallback) {
		var resolvedPath = mampFile._parseFilePath(path);
		if (resolvedPath !== null) {
			cordovaRequestLocalFileSystem.resolveLocalFileSystemURL(resolvedPath, function (dirEntry) {
				var wrontTypeError = function(e) {
					dirEntry.getDirectory(fileName, {create: false, exclusive: false}, function(fileEntry) {
	        			fileEntry.getMetadata(successCallback, errorCallback);
	    			}, errorCallback);
				};

    			dirEntry.getFile(fileName, {create: false, exclusive: false}, function(fileEntry) {
	        		fileEntry.getMetadata(successCallback, errorCallback);
	    		}, wrontTypeError);
    		}, errorCallback);
		} else {
			console.log("INVALID Path!!");
			errorCallback(mampFile._generateError(1, "INVALID Path!!"));

		}
	},

	/**
	 * 读取文件数据.
	 *
	 * @param FileReadType type                读取方式
	 * @param FileStoragePath path             根目录类型
	 * @param String fileName                  文件的相对路径，如"test/data/data2.txt"
	 * @param {function} successCallback       (OPTIONAL)获取成功的回调，参数为string类型；读取方式为ArrayBuffer时，参数可以使用Uint8Array()处理
	 * @param {function} errorCallback         (OPTIONAL)获取失败的回调
	 */
	read:function(type, path, fileName, successCallback, errorCallback) {
		var resolvedPath = mampFile._parseFilePath(path);
		if (resolvedPath !== null) {
			cordovaRequestLocalFileSystem.resolveLocalFileSystemURL(resolvedPath, function (dirEntry) {
    			dirEntry.getFile(fileName, {create: false, exclusive: false}, function(fileEntry) {

    					var doReader = function(file) {
    						var fileReader = new FileReader();

	        				fileReader.onloadend = function() {
				            	console.log("Successful file read: " + this.result);
				            	successCallback(this.result);
				        	};

				        	fileReader.onerror = function (e) {
					            console.log("Failed file read: " + e.toString());
					            errorCallback(e);
					        };

				        	if (type === mampFile.FileReadType.Text) {
				        		fileReader.readAsText(file);
				        	} else if (type === mampFile.FileReadType.DataURL) {
				        		fileReader.readAsDataURL(file);
				        	} else if (type === mampFile.FileReadType.BinaryString) {
				        		fileReader.readAsBinaryString(file);
				        	} else if (type === mampFile.FileReadType.ArrayBuffer) {
				        		fileReader.readAsArrayBuffer(file);
				        	} else {
				        		console.log("INVALID File Read Type!!");
				        		errorCallback(mampFile._generateError(1, "INVALID File Read Type!!"));
				        	}
        					
    					};
	        			

        				fileEntry.file(doReader, errorCallback);
	    			}, errorCallback);
    		}, errorCallback);
		} else {
			console.log("INVALID Path!!");
			errorCallback(mampFile._generateError(1, "INVALID Path!!"));
		}
	},

	/**
	 * 向指定文件写入数据.
	 *
	 * @param FileStoragePath path             根目录类型
	 * @param String fileName                  文件的相对路径，如"test/data/data2.txt"
	 * @param dataObj fromPath                 待写入数据，类型为string或blob
	 * @param bool isAppend                    是否为添加写模式。值为false或null时，默认为覆盖写模式
	 * @param {function} successCallback       (OPTIONAL)写入成功的回调
	 * @param {function} errorCallback         (OPTIONAL)写入失败的回调
	 */
	write:function(path, fileName, dataObj, isAppend, successCallback, errorCallback) {
		var resolvedPath = mampFile._parseFilePath(path);
		if (resolvedPath !== null) {
			cordovaRequestLocalFileSystem.resolveLocalFileSystemURL(resolvedPath, function (dirEntry) {
    			dirEntry.getFile(fileName, {create: false, exclusive: false}, function(fileEntry) {
	        		mampFile._writeFile(fileEntry, dataObj, isAppend, successCallback, errorCallback);
	    		}, errorCallback);
    		}, errorCallback);
		} else {
			console.log("INVALID Path!!");
			errorCallback(mampFile._generateError(1, "INVALID Path!!"));

		}
	},

	/**
	* 向服务地址上传指定的文件
	* @param FileStoragePath path         根目录类型
	* @param String fileName             文件的相对路径，如"test/data/data2.txt"
	* @param String server               服务端URL
	* @param {function} successCallback  (OPTIONAL)上传成功的回调
	* @param {function} errorCallback    (OPTIONAL)上传失败的回调
	* @param {FileUploadOptions} options (OPTIONAL)上传文件操作的参数，具体内容可参考 #http://cordova.apache.org/docs/en/6.x/reference/cordova-plugin-file-transfer/index.html#upload
	* return FileTranfer                 文件传输句柄，用于在停止上传操作时作为参数传递
	*/
	upload:function(path, fileName, server, successCallback, errorCallback, options) {
		var resolvedPath = mampFile._parseFilePath(path);
		if (resolvedPath !== null) {
			cordovaRequestLocalFileSystem.resolveLocalFileSystemURL(resolvedPath, function (dirEntry) {
    			dirEntry.getFile(fileName, {create: false, exclusive: false}, function(fileEntry) {
	        		var fileTranfer = new FileTransfer();
	        		fileTranfer.upload(fileEntry.toURL(), encodeURI(server), successCallback, errorCallback, options, false);
	        		return fileTranfer;
	    		}, errorCallback);
    		}, errorCallback);
		} else {
			console.log("INVALID Path!!");
			errorCallback(mampFile._generateError(1, "INVALID Path!!"));

		}
	},

	/**
    	* 向服务地址上传指定的文件
    	* @param String server               服务端URL
    	* @param [] filePaths               需要上传的本地文件路径，支持多张
    	* @param {function} callback  (OPTIONAL)上传的回调，会返回上传服务器返回的response
    	* @param {FileUploadOptions} options (OPTIONAL)上传文件操作的参数，具体内容可参考 #http://cordova.apache.org/docs/en/6.x/reference/cordova-plugin-file-transfer/index.html#upload
    	* return FileTranfer                 文件传输句柄，用于在停止上传操作时作为参数传递
    	*/
    	uploadToServer:function(server,filePaths, callback,options) {
        	var requestCount = filePaths.length;

        	var rets = [];
            var requestCallBack = function(ret){
            	rets.push(ret);
    	       	requestCount--;
               	if (requestCount == 0) {
               		var sortArr = rets.sort(function(a,b){
               			return a.sortIndex - b.sortIndex;
               		});
               		callback(sortArr);
               	}
            }
            for(var i = 0; i < filePaths.length; i++){
    			var fileTranfer = new FileTransfer();
                var index = fileTranfer._id;
                   (function(index) {
                    fileTranfer.upload(filePaths[i], encodeURI(server), function(ret){
                                       ret.sortIndex = index;
                                       requestCallBack(ret);
                                       }, function(ret){
                                       ret.sortIndex = index;
                                       requestCallBack(ret);
                                       }, options, false);
                    }(index));

            }
    	},

	/**
	* 从服务地址下载指定的文件
	* @param String source               待下载文件的服务地址
	* @param FileStoragePath path        根目录类型
	* @param String fileName             文件的存储相对路径，如"test/data/data2.txt"
	* @param {function} successCallback  (OPTIONAL)下载成功的回调
	* @param {function} errorCallback    (OPTIONAL)下载失败的回调
	* @param {FileDownloadOptions} options (OPTIONAL)下载文件操作的参数，具体内容可参考 #http://cordova.apache.org/docs/en/6.x/reference/cordova-plugin-file-transfer/index.html#download
	* return FileTranfer                 文件传输句柄，用于在停止上传操作时作为参数传递
	*/
	download:function(source, path, fileName, successCallback, errorCallback, options) {
		var resolvedPath = mampFile._parseFilePath(path);
		if (resolvedPath !== null) {
			cordovaRequestLocalFileSystem.resolveLocalFileSystemURL(resolvedPath, function (dirEntry) {
    			dirEntry.getFile(fileName, { create: true, exclusive: false }, function(fileEntry) {
	        		var fileTranfer = new FileTransfer();
	        		fileTranfer.download(source, fileEntry.toURL(), successCallback, errorCallback, false, options);
	        		return fileTranfer;
	    		}, errorCallback);
    		}, errorCallback);
		} else {
			console.log("INVALID Path!!");
			errorCallback(mampFile._generateError(1, "INVALID Path!!"));
		}
	},

	/**
	* 停止进行中的文件传输请求
	* @param FileTranfer fileTranferObj     文件传输句柄
	*/
	abortFileTranfer:function(fileTranferObj) {
		if (fileTranferObj && (typeof fileTranferObj === "FileTransfer")) {
			fileTranferObj.abort();
		} else {
			console.log("INVLID FileTransfer Object!!");
		}
	},
	/**
    * 向服务地址上传指定的文件
    * @param {array} filePathList 本地文件列表
    * @param {function} successCallback  (OPTIONAL)上传成功的回调
    * @param {function} errorCallback    (OPTIONAL)上传失败的回调
    */
    uploadToOSS:function(filePathList, successCallback, errorCallback) {
        exec(successCallback, errorCallback, 'FileTransfer', 'uploadToOSS', [filePathList]);
    },
    /*	文件预览接口，使用系统能力打开某个文件路径
    @param url  文件完整路径
    @param type 文件类型
    @param name 文件名字，不带后缀，可不传
    */
    filePreview:function(url,type,name){
    	exec(null,null,"File","filePreview",[{"url":url||'',"type":type||'',"name":name||''}]);
    }
};

module.exports = mampFile;
});
